#ifndef _I386_MEMORY_H
#define _I386_MEMORY_H


/* x86特性 */
#define I386_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */

/*
* Alternative instructions for different CPU types or capabilities.
*
* This allows to use optimized instructions even on generic binary
* kernels.
*
* length of oldinstr must be longer or equal the length of newinstr
* It can be padded with nops as needed.
*
* For non barrier like inlines please define new variants
* without volatile and memory clobber.
*/
#define alternative(oldinstr, newinstr, feature) \
asm volatile ("661:\n\t" oldinstr "\n662:\n" \
      ".section .altinstructions,\"a\"\n" \
      "   .align 4\n" \
      "   .long 661b\n"          /* label */ \
      "   .long 663f\n"    /* new instruction */ \
      "   .byte %c0\n"          /* feature bit */ \
      "   .byte 662b-661b\n"    /* sourcelen */ \
      "   .byte 664f-663f\n"    /* replacementlen */ \
      ".previous\n" \
      ".section .altinstr_replacement,\"ax\"\n" \
      "663:\n\t" newinstr "\n664:\n" /* replacement */\
      ".previous" :: "i" (feature) : "memory")

#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", I386_FEATURE_XMM2)
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", I386_FEATURE_XMM2)

#ifdef CONFIG_I386_OOSTORE
/* Actually there are no OOO store capable CPUs for now that do SSE, 
but make it already an possibility. */
#define wmb() Alternative("lock; addl $0,0(%%esp)", "sfence", I386_FEATURE_XMM)
#else
#define wmb() __asm__ __volatile__ ("": : :"memory")
#endif

/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")

#define	flush_tlb_one(addr)	\
	__asm__ __volatile__	("invlpg	(%0)	\n\t"::"r"(addr):"memory")
/*

*/

#define flush_tlb()						\
do								\
{								\
	unsigned long	tmpreg;					\
	__asm__ __volatile__ 	(				\
				"movl	%%cr3,	%0	\n\t"	\
				"movl	%0,	%%cr3	\n\t"	\
				:"=r"(tmpreg)			\
				:				\
				:"memory"			\
				);				\
}while(0)


#define mfence() 	__asm__ __volatile__ ("mfence	\n\t":::"memory")


unsigned int get_ram_size();

/* 最少的内存硬件大小 */
#define MIN_RAM_SIZE             (32 * MB)

// 0MB~1MB是体系结构相关的内存分布
#define BIOS_MEM_ADDR               0
#define BIOS_MEM_SIZE               (1 * MB)     // 1MB

// 1MB~2MB是内核镜像
#define IMAGE_MEM_ADDR             (BIOS_MEM_ADDR + BIOS_MEM_SIZE)
#define IMAGE_MEM_SIZE             (1 * MB)     // 1MB

// 2MB~8MB是系统重要信息的存放地址
#define MATERIAL_MEM_ADDR           (IMAGE_MEM_ADDR + IMAGE_MEM_SIZE)
#define MATERIAL_MEM_SIZE           (6 * MB)   // 6MB

// 8M以上是静态内存开始地址
#define STATIC_MEM_ADDR             (MATERIAL_MEM_ADDR + MATERIAL_MEM_SIZE) 

#define TOP_MEM_ADDR                0xFFFFFFFF // 最高内存地址

/* 空内存，当前页目录表物理地址的映射（不可访问） */
#define NULL_MEM_SIZE                (4 * MB)
#define NULL_MEM_ADDR                (TOP_MEM_ADDR - NULL_MEM_SIZE + 1)

/* 内核映射的虚拟地址的起始偏移值 */
#define KERNEL_VADDR_OFFSET         0x80000000

/* 内核栈顶 */
#define KERNEL_STATCK_TOP		    (KERNEL_VADDR_OFFSET + 0x9f000)

#endif   /* _I386_MEMORY_H */
